import requests
import pandas as pd
import json
import time
from datetime import datetime
import threading

class TxData:

    def __init__(self, update_interval=10):
        self.update_interval = update_interval  # 更新间隔（秒）
        self.is_trading = False
        self.last_data = {}
        self.callbacks = []


    def tx_data_k(self):
        url ="https://ifzq.gtimg.cn/appstock/app/kline/mkline?param=sh603937,m5,,50"
        # datadf =http.api_to_dataframe(url)
        datadf =self.get_realtime_m5_data("sh603937",100)
        # print(datadf)
        return datadf



    def is_trading_time(self):
        """检查当前是否为A股交易时间"""
        now = datetime.now()
        # 排除周末
        if now.weekday() >= 5:
            return False

        # 检查交易时段
        current_time = now.time()
        morning_start = datetime.strptime('09:30:00', '%H:%M:%S').time()
        morning_end = datetime.strptime('11:30:00', '%H:%M:%S').time()
        afternoon_start = datetime.strptime('13:00:00', '%H:%M:%S').time()
        afternoon_end = datetime.strptime('15:00:00', '%H:%M:%S').time()

        return ((morning_start <= current_time <= morning_end) or
                (afternoon_start <= current_time <= afternoon_end))


    def get_realtime_m5_data(self,stock_code, count=300, retry_count=3):
        """
        获取实时M5数据（支持盘中）

        参数:
        - stock_code: 股票代码
        - count: 获取的数据条数
        - retry_count: 重试次数
        """

        url ="https://ifzq.gtimg.cn/appstock/app/kline/mkline?param=sz159755,m5,,500"
        url = f"http://ifzq.gtimg.cn/appstock/app/kline/mkline?param={stock_code},m5,,{count}"

        for attempt in range(retry_count):
            try:
                headers = {
                    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
                    'Referer': 'http://quote.eastmoney.com',
                    'Accept': 'application/json, text/javascript, */*; q=0.01'
                }

                response = requests.get(url, headers=headers, timeout=5)
                response.raise_for_status()

                data = json.loads(response.text)

                # 解析数据
                if 'data' in data and data['data']:
                    # 尝试不同的键名
                    possible_keys = [f"{stock_code}_m5", "m5", "data"]
                    for key in possible_keys:
                        if key in data['data']:
                            kline_data = data['data'][key].get('m5', [])
                            break
                    else:
                        # 如果都没找到，取第一个键
                        first_key = list(data['data'].keys())[0]
                        kline_data = data['data'][first_key].get('m5', [])

                    if kline_data:
                        df = self._parse_kline_data(kline_data)
                        return df

                time.sleep(1)  # 失败后等待1秒再重试

            except Exception as e:
                print(f"第{attempt + 1}次尝试失败: {e}")
                if attempt == retry_count - 1:
                    print(f"获取 {stock_code} 数据失败")
                time.sleep(1)

        return None


    def _parse_kline_data(self,kline_data):
        """解析K线数据"""
        df = pd.DataFrame(kline_data, columns=['时间', '开盘价', '收盘价', '最高价', '最低价', '成交量',"对象",'成交额'])

        # 转换数据类型
        df['时间'] = pd.to_datetime(df['时间'])
        df['开盘价'] = pd.to_numeric(df['开盘价'])
        df['收盘价'] = pd.to_numeric(df['收盘价'])
        df['最高价'] = pd.to_numeric(df['最高价'])
        df['最低价'] = pd.to_numeric(df['最低价'])
        df['成交量'] = pd.to_numeric(df['成交量'])
        df['成交额'] = pd.to_numeric(df['成交额'])

        # 设置索引
        # df = df.set_index('时间').sort_index()

        return df


    def start_realtime_monitoring(self, stock_codes, callback=None):
        """
        启动实时监控
        """
        if callback:
            self.callbacks.append(callback)

        self.is_trading = self.is_trading_time()

        if not self.is_trading:
            print("当前不是交易时间")
            return

        print(f"开始实时监控: {stock_codes}")

        # 启动监控线程
        monitor_thread = threading.Thread(
            target=self._monitoring_loop,
            args=(stock_codes,),
            daemon=True
        )
        monitor_thread.start()

        return monitor_thread


    def _monitoring_loop(self, stock_codes):
        """监控循环"""
        while self.is_trading_time():
            try:
                current_time = datetime.now()
                print(f"\n[{current_time.strftime('%H:%M:%S')}] 更新数据...")

                for code in stock_codes:
                    data = self.get_realtime_m5_data(code, count=50)

                    if data is not None:
                        self.last_data[code] = data

                        # 检查是否有新K线
                        if code in self.last_data:
                            old_len = len(self.last_data[code])
                            new_len = len(data)

                            if new_len > old_len:
                                new_bars = new_len - old_len
                                print(f"{code} 新增 {new_bars} 根K线")

                        # 触发回调
                        for callback in self.callbacks:
                            try:
                                callback(code, data)
                            except Exception as e:
                                print(f"回调函数错误: {e}")

                # 等待下次更新
                time.sleep(self.update_interval)

            except Exception as e:
                print(f"监控循环错误: {e}")
                time.sleep(5)


    def get_last_complete_bar(self, stock_code):
        """
        获取最新完整的5分钟K线（非当前正在形成的）
        """
        if stock_code not in self.last_data:
            return None

        data = self.last_data[stock_code]
        if len(data) == 0:
            return None

        # 返回最后一条完整数据（排除可能不完整的当前K线）
        return data.iloc[-2] if len(data) > 1 else data.iloc[-1]

